import datetime
import random
import subprocess
import sys
import json
from flask import Flask, request, jsonify, send_from_directory
import os
from dotenv import load_dotenv


# 确保依赖安装的函数
def ensure_dependencies():
    required_packages = ['pypinyin', 'flask', 'cozepy', 'python-dotenv']
    for package in required_packages:
        try:
            __import__(package)
        except ImportError:
            print(f"安装依赖包: {package}")
            subprocess.check_call([sys.executable, "-m", "pip", "install", package])


# 先安装依赖，再导入需要的包
ensure_dependencies()
from pypinyin import pinyin as py_pinyin, Style
from cozepy import Coze, TokenAuth, COZE_CN_BASE_URL, Message, ChatStatus

# 初始化Flask应用，显式指定静态文件目录
app = Flask(__name__, static_folder='static', static_url_path='/static')

# 确保static文件夹存在
if not os.path.exists('static'):
    os.makedirs('static')

# 成语池持久化存储文件
USED_IDIOMS_FILE = "used_idioms.json"

load_dotenv()

# 扩展初始成语库至50个常用成语（确保无重复）
COMMON_IDIOMS = [
    "一心一意", "千军万马", "悬梁刺股", "凿壁偷光", "画龙点睛", "画蛇添足",
    "守株待兔", "亡羊补牢", "刻舟求剑", "掩耳盗铃", "井底之蛙", "邯郸学步",
    "一马当先", "三心二意", "四面八方", "五光十色", "六神无主", "七上八下",
    "八面玲珑", "九牛一毛", "十全十美", "百发百中", "千方百计", "万无一失",
    "天长地久", "日新月异", "山高水长", "风和日丽", "花红柳绿", "鸟语花香",
    "人杰地灵", "国泰民安", "安居乐业", "勤能补拙", "学无止境", "半途而废",
    "坚持不懈", "实事求是", "与时俱进", "精益求精", "众志成城", "百折不挠",
    "举一反三", "温故知新", "不耻下问", "触类旁通", "礼尚往来", "雪中送炭",
    "锦上添花", "妙手回春", "望梅止渴", "画饼充饥"
]

# 验证成语库是否有重复
if len(COMMON_IDIOMS) != len(set(COMMON_IDIOMS)):
    duplicates = [idiom for idiom in COMMON_IDIOMS if COMMON_IDIOMS.count(idiom) > 1]
    print(f"警告: 成语库中存在重复成语: {duplicates}")


class IdiomGame:
    def __init__(self):
        self.api_token = os.environ.get("COZE_API_TOKEN",
                                        "pat_RXLKRngglw1pvfYpkItI909bAHij2mwkXqFhn8S8EVMahqbtfPJMEQ5kxrTQtR9S")
        self.bot_id = os.environ.get("BOT_ID", "7564308075587944458")
        self.user_id = os.environ.get("USER_ID", "758039436082793")
        self.used_idioms = self.load_used_idioms()  # 跨游戏持久化的成语记录
        self.current_idiom = self.get_random_idiom()  # 机器人当前成语
        self.game_history = []
        self.current_game_idioms = set()  # 当前局已使用成语集合（新增）
        self.current_game_idioms.add(self.current_idiom)  # 添加初始成语（新增）
        self.coze = Coze(
            auth=TokenAuth(token=self.api_token),
            base_url=COZE_CN_BASE_URL
        )
        print(f"游戏初始化完成 - 当前成语: {self.current_idiom}, 已使用成语数: {len(self.used_idioms)}")

    def load_used_idioms(self):
        """从文件加载已使用成语记录"""
        try:
            if os.path.exists(USED_IDIOMS_FILE):
                with open(USED_IDIOMS_FILE, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    print(f"从{USED_IDIOMS_FILE}加载已使用成语: {data}")
                    return set(data)
            else:
                print(f"{USED_IDIOMS_FILE}不存在，初始化空集合")
                return set()
        except Exception as e:
            print(f"加载已使用成语记录失败: {str(e)}，使用空集合")
            return set()

    def save_used_idioms(self):
        """保存已使用成语记录到文件"""
        try:
            with open(USED_IDIOMS_FILE, 'w', encoding='utf-8') as f:
                json.dump(list(self.used_idioms), f, ensure_ascii=False, indent=2)
            print(f"已保存{len(self.used_idioms)}个已使用成语到{USED_IDIOMS_FILE}")
        except Exception as e:
            print(f"保存已使用成语记录失败: {str(e)}")

    def get_random_idiom(self):
        """获取不重复的随机初始成语，添加详细日志"""
        # 验证成语库完整性
        if not COMMON_IDIOMS:
            raise ValueError("成语库为空，请检查COMMON_IDIOMS配置")

        # 检查是否有重复成语
        if len(COMMON_IDIOMS) != len(set(COMMON_IDIOMS)):
            duplicates = [idiom for idiom in COMMON_IDIOMS if COMMON_IDIOMS.count(idiom) > 1]
            print(f"警告: 成语库中存在重复成语: {duplicates}")

        # 如果所有成语都用过了，重置已使用集合
        if len(self.used_idioms) >= len(COMMON_IDIOMS):
            self.used_idioms = set()
            print(f"所有{len(COMMON_IDIOMS)}个初始成语已用完，重置成语池")

        # 从未使用的成语中随机选择
        available_idioms = [idiom for idiom in COMMON_IDIOMS if idiom not in self.used_idioms]
        print(f"可用成语: {available_idioms} (共{len(available_idioms)}个)")

        if not available_idioms:
            print("紧急情况: 可用成语为空，强制重置")
            self.used_idioms = set()
            available_idioms = COMMON_IDIOMS.copy()

        # 使用随机选择并记录日志
        selected_idiom = random.choice(available_idioms)
        print(f"从{len(available_idioms)}个可用成语中选择: {selected_idiom}")

        self.used_idioms.add(selected_idiom)
        self.save_used_idioms()  # 保存更新后的已使用成语集合

        return selected_idiom

    def add_idiom_to_history(self, user_idiom, bot_idiom):
        """添加成语到历史记录"""
        record = {
            "user": user_idiom,
            "bot": bot_idiom,
            "timestamp": datetime.datetime.now().strftime("%H:%M:%S"),
        }
        self.game_history.insert(0, record)

        if len(self.game_history) > 20:
            self.game_history = self.game_history[:20]

    def is_valid_idiom_format(self, idiom):
        """仅验证成语格式是否正确（四字中文）"""
        if len(idiom) != 4:
            return False, "成语必须是四个字"

        if not all('\u4e00' <= c <= '\u9fff' for c in idiom):
            return False, "成语必须由中文汉字组成"

        return True, ""

    def get_pinyin(self, char):
        """获取汉字拼音，返回不带声调的拼音字符串"""
        # 使用pypinyin获取拼音，不带声调
        pinyin_list = py_pinyin(char, style=Style.NORMAL, errors='ignore')
        if pinyin_list and pinyin_list[0]:
            return pinyin_list[0][0].lower()
        return ""

    def check_pronunciation_match(self, previous_idiom, next_idiom):
        """
        检查发音匹配: next_idiom的首字发音与previous_idiom的尾字发音是否相同
        previous_idiom: 上一个成语（尾字作为发音基准）
        next_idiom: 下一个成语（首字需要匹配发音）
        """
        if not previous_idiom or not next_idiom:
            return False, "", ""

        # 获取上一个成语尾字拼音
        last_char = previous_idiom[-1]
        last_pinyin = self.get_pinyin(last_char)

        # 获取下一个成语首字拼音
        first_char = next_idiom[0]
        first_pinyin = self.get_pinyin(first_char)

        return last_pinyin == first_pinyin, last_pinyin, first_pinyin

    def validate_idiom_content(self, idiom):
        """使用COZE验证成语内容是否有效"""
        try:
            messages = [
                Message(
                    role="user",
                    content=f"请判断'{idiom}'是否为一个标准的汉语成语。只需回答'是'或'否'，不要添加任何额外解释。",
                    content_type="text",
                    type="question"
                )
            ]

            chat = self.coze.chat.create(
                bot_id=self.bot_id,
                user_id=self.user_id,
                additional_messages=messages,
                auto_save_history=True
            )

            while chat.status == ChatStatus.IN_PROGRESS:
                chat = self.coze.chat.retrieve(
                    conversation_id=chat.conversation_id,
                    chat_id=chat.id
                )

            if chat.status == ChatStatus.COMPLETED:
                messages = self.coze.chat.messages.list(
                    conversation_id=chat.conversation_id,
                    chat_id=chat.id
                )

                for msg in messages:
                    if hasattr(msg, 'role') and msg.role == 'assistant':
                        response = msg.content.strip().lower()
                        if "是" in response:
                            return True, ""
                        else:
                            return False, "输入不是有效的成语，请重新输入"

            return False, "无法验证成语有效性，请重试"

        except Exception as e:
            print(f"成语验证错误: {str(e)}")
            return False, "成语验证失败，请重试"

    def get_coze_response(self, user_input):
        """获取COZE的成语接龙响应，增加当前局重复检查和重试机制"""
        max_attempts = 5  # 最多重试5次
        attempt = 0

        while attempt < max_attempts:
            try:
                messages = [
                    Message(
                        role="user",
                        content=f"成语接龙游戏，规则：下一个成语的第一个字发音需要与上一个成语的最后一个字发音相同。上一个成语是：{user_input}，请接下一个四字成语，只返回成语本身，不要添加任何解释或额外文字。",
                        content_type="text",
                        type="question"
                    )
                ]

                chat = self.coze.chat.create(
                    bot_id=self.bot_id,
                    user_id=self.user_id,
                    additional_messages=messages,
                    auto_save_history=True
                )

                while chat.status == ChatStatus.IN_PROGRESS:
                    chat = self.coze.chat.retrieve(
                        conversation_id=chat.conversation_id,
                        chat_id=chat.id
                    )

                if chat.status == ChatStatus.COMPLETED:
                    messages = self.coze.chat.messages.list(
                        conversation_id=chat.conversation_id,
                        chat_id=chat.id
                    )

                    sdk_response = None
                    for msg in messages:
                        if hasattr(msg, 'role') and msg.role == 'assistant':
                            sdk_response = "".join(filter(lambda x: '\u4e00' <= x <= '\u9fff', msg.content.strip()))
                            break

                    if sdk_response and len(sdk_response) >= 4:
                        bot_idiom = sdk_response[:4]

                        # 检查当前局是否已使用该成语（新增核心逻辑）
                        if bot_idiom in self.current_game_idioms:
                            print(f"机器人生成重复成语: {bot_idiom}，正在重试...")
                            attempt += 1
                            continue  # 重复则重试

                        # 检查成语格式
                        is_valid, _ = self.is_valid_idiom_format(bot_idiom)
                        if is_valid:
                            # 添加到当前局已使用成语集合（新增）
                            self.current_game_idioms.add(bot_idiom)
                            return bot_idiom

            except Exception as e:
                print(f"COZE API调用错误: {str(e)}")
                attempt += 1

        # 多次失败后，从成语库随机选择一个未使用的成语（新增备用方案）
        print(f"多次尝试后仍无法获取有效成语，使用备用方案")
        available_idioms = [idiom for idiom in COMMON_IDIOMS if idiom not in self.current_game_idioms]
        if available_idioms:
            bot_idiom = random.choice(available_idioms)
            self.current_game_idioms.add(bot_idiom)
            return bot_idiom

        # 极端情况：所有成语都已使用，返回随机成语
        print("警告：当前局所有成语已用尽")
        bot_idiom = random.choice(COMMON_IDIOMS)
        self.current_game_idioms.add(bot_idiom)
        return bot_idiom

    def play_turn(self, user_input):
        """处理一轮游戏，增加用户输入重复检查（新增核心逻辑）"""
        # 1. 验证用户输入是否为空
        if not user_input:
            return {"success": False, "error": "请输入成语"}

        # 2. 验证成语格式（四字中文）
        is_valid_format, error_msg = self.is_valid_idiom_format(user_input)
        if not is_valid_format:
            return {"success": False, "error": error_msg}

        # 3. 检查当前局是否已使用该成语（新增核心逻辑）
        if user_input in self.current_game_idioms:
            return {"success": False, "error": f"该成语'{user_input}'已在本局使用，请换一个成语"}

        # 4. 验证成语内容是否有效（使用COZE）
        is_valid_content, error_msg = self.validate_idiom_content(user_input)
        if not is_valid_content:
            return {"success": False, "error": error_msg}

        # 5. 验证用户接龙发音是否匹配
        match, last_pinyin, first_pinyin = self.check_pronunciation_match(self.current_idiom, user_input)
        if not match:
            last_char = self.current_idiom[-1]
            user_first_char = user_input[0]
            return {"success": False,
                    "error": f"用户成语首字发音不匹配！机器人成语尾字 '{last_char}'({last_pinyin})，您输入的成语首字 '{user_first_char}'({first_pinyin})"}

        # 添加用户成语到当前局已使用集合（新增）
        self.current_game_idioms.add(user_input)

        # 6. 获取机器人接龙成语
        bot_idiom = self.get_coze_response(user_input)
        if not bot_idiom:
            return {"success": False, "error": "无法获取机器人响应，请重试"}

        # 7. 更新游戏状态
        self.add_idiom_to_history(user_input, bot_idiom)
        self.current_idiom = bot_idiom

        return {
            'success': True,
            'bot_idiom': bot_idiom,
            'current_idiom': self.current_idiom,
            'history': self.game_history
        }

    def restart_game(self):
        """重新开始一局游戏，重置当前局成语集合（修改核心逻辑）"""
        print(f"=== 重新开始游戏 ===")
        # 重置当前局成语集合（新增核心逻辑）
        self.current_game_idioms = set()
        # 获取新的初始成语
        self.current_idiom = self.get_random_idiom()
        # 添加到当前局成语集合
        self.current_game_idioms.add(self.current_idiom)
        self.game_history = []
        print(f"新游戏初始成语: {self.current_idiom}，当前局成语集合已重置")
        return {"success": True, "initial_idiom": self.current_idiom}


# 创建游戏实例
game = IdiomGame()


@app.route('/api/start', methods=['GET'])
def start_game():
    return jsonify({
        "success": True,
        "initial_idiom": game.current_idiom
    })


@app.route('/api/play', methods=['POST'])
def play_game():
    data = request.get_json()
    user_input = data.get('idiom', '').strip()

    result = game.play_turn(user_input)
    return jsonify(result)


@app.route('/api/restart', methods=['POST'])
def restart_game():
    result = game.restart_game()
    return jsonify(result)


@app.route('/', methods=['GET'])
def serve_frontend():
    return send_from_directory('static', 'index.html')


@app.route('/static/<path:path>', methods=['GET'])
def serve_static_files(path):
    return send_from_directory('static', path)


if __name__ == '__main__':
    app.run(debug=True, port=5000)